/*
 * @(#)DatepickerTag.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.framework.taglib.html;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;

import org.apache.struts.util.RequestUtils;
import org.apache.struts.util.ResponseUtils;

import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.Utility;
import com.dcivision.framework.web.WebUtil;


/**
    DatepickerTag.java

    <p>This class is to extend the TextTag provided by Apache Struts.<p>
    <p>Modification in "struts-html.tld"<br>

  <pre>
     [ADDED]
      &lt;tagclass&gt;com.dcivision.framework.taglib.html.DatepickerTag&lt;/tagclass&gt;
      &lt;name&gt;topPos&lt;/name&gt;
      &lt;required&gt;false&lt;/required&gt;
      &lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt;
      &lt;/attribute&gt;
      &lt;attribute&gt;
      &lt;name&gt;dateFormat&lt;/name&gt;
      &lt;required&gt;false&lt;/required&gt;
      &lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt;
      &lt;/attribute&gt;
      &lt;attribute&gt;
      &lt;name&gt;textOnly&lt;/name&gt;
      &lt;required&gt;false&lt;/required&gt;
      &lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt;
      &lt;/attribute&gt;
      &lt;name&gt;date&lt;/name&gt;
      &lt;required&gt;false&lt;/required&gt;
      &lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt;
      &lt;/attribute&gt;
      &lt;attribute&gt;
      &lt;name&gt;time&lt;/name&gt;
      &lt;required&gt;false&lt;/required&gt;
      &lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt;
      &lt;/attribute&gt;
      &lt;attribute&gt;
      &lt;name&gt;ontimechange&lt;/name&gt;
      &lt;required&gt;false&lt;/required&gt;
      &lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt;
      &lt;/attribute&gt;
      &lt;attribute&gt;
      &lt;name&gt;defaultToday&lt;/name&gt;
      &lt;required&gt;false&lt;/required&gt;
      &lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt;
      &lt;/attribute&gt;
  </pre>
    </p>

  <p>USAGE:</p>
  <p>The following example shows the dateInput usage, with the date picker top position set. The date format used in the example is 'dd/mm/yyyy'  </p>
  <p>if date is set to true, date field will be displayed and allow user to input; if time is set to true, time selection boxes will be display and allow user to select time</p>
  <p><code>&lt;html:datepicker property='updateDate' <strong> dateFormat='dd/mm/yyyy' date='true' time='true' ontimechange='return calTime();' defaultToday='true' needReload ='false' digital='false' </strong>/&gt;</code></p>

  @author Beyond Qu
  @company DCIVision Limited
  @creation date   02/06/2004
  @version $Revision: 1.33.2.7 $
 */
public class DatepickerTag extends TextTag {

  public static final String REVISION = "$Revision: 1.33.2.7 $";


  /** Holds value of property dateFormat. */
  private String dateFormat;

  /** Holds value of property date. */
  private boolean date;

  /** Holds value of property time. */
  private boolean time;

  /** Holds value of property ontimechange. */
  private String ontimechange = null;

  /** Holds value of property defaultToday. */
  private boolean defaultToday;

  /** Holds value of property after choice a day reload this page. */
  private boolean needReload;

  /** Holds value of property digital. */
  private boolean digital;

  private String changeProperty;
  
  private String formName="";
  
  private Integer verticalOffset = null;
  
  private Integer horizontalOffset = null;
  
  
  public Integer getHorizontalOffset() {
    return horizontalOffset;
}

public void setHorizontalOffset(Integer horizontalOffset) {
    this.horizontalOffset = horizontalOffset;
}

public Integer getVerticalOffset() {
    return verticalOffset;
}

public void setVerticalOffset(Integer verticalOffset) {
    this.verticalOffset = verticalOffset;
}

/** default constructor
   */
  public DatepickerTag() {
    super();
    reset();
  }

  public void reset(){
    this.setDateFormat(SystemParameterFactory.getSystemParameter(SystemParameterConstant.DATE_FORMAT));
    this.setSize(Integer.toString(dateFormat!=null?dateFormat.length():10));
    this.setMaxlength(Integer.toString(dateFormat!=null?dateFormat.length():10));
    this.setDate(true);
    this.setTime(false);
    this.setDefaultToday(false);
    this.setValue(null);
    this.setNeedReload(false);
    this.setDigital(true);
    this.setOnblur(null);
    this.setOnchange("false");	
    this.setVerticalOffset(null);
    this.setHorizontalOffset(null);
  }


  /** Getter for property dateFormat.
   * @return Value of property dateFormat.
   */
  public String getDateFormat() {
    return this.dateFormat;
  }

  /** Setter for property dateFormat.
   * @param dateFormat New value of property dateFormat.
   */
  public void setDateFormat(String dateFormat) {
    this.dateFormat = dateFormat;
  }

  /** overriden parent's doStartTag
   * @return
   * @throws JspException
   */
  
  public int doStartTag() throws javax.servlet.jsp.JspException {
    int retValue = SKIP_BODY;
    JspWriter out = pageContext.getOut();
    FormTag formTag = (FormTag)BodyTagSupport.findAncestorWithClass(this, FormTag.class);
    HttpServletRequest request = (HttpServletRequest)this.pageContext.getRequest();
    String actionMode = (String) request.getAttribute(GlobalConstant.ACTION_MODE);
    boolean isViewDatePicker = false;

    if (!Utility.isEmpty(request.getParameter("isViewDatePicker"))) {
      if ("TRUE".equals(request.getParameter("isViewDatePicker")) ||
          "True".equals(request.getParameter("isViewDatePicker")) ||
          "true".equals(request.getParameter("isViewDatePicker")) ) {
        isViewDatePicker = true;
      }

    }

    try {
      //get super's onBlur() value
      String sOnBlurStr = !Utility.isEmpty(this.getOnblur()) ? this.getOnblur() : "";
      String sOnTimeChangeStr = this.getOntimechange();
      String sPropertyName = this.getProperty();
      String sChangePropertyName = "dummy_"+this.getChangeProperty();
      String sDatetimeStr = this.getValue();
      String sDBDatetimeFormat = SystemParameterFactory.getSystemParameter(SystemParameterConstant.DB_DATETIME_FORMAT);
      String sDatePart="";
      int iHourPart=-1, iMinutePart=-1;
      if (value != null) {
        sDatetimeStr = ResponseUtils.filter(value);
      } else {
        //Object value;
        //value = RequestUtils.lookup(pageContext, name, property, null);
        if (value == null && this.getDefaultToday()
          && !GlobalConstant.NAV_MODE_VIEW.equals(actionMode) && !GlobalConstant.NAV_MODE_EDIT.equals(actionMode) && !GlobalConstant.NAV_MODE_REFRESH.equals(actionMode) ) {
          Calendar today = Calendar.getInstance();
          if (!time) {
            today.set(Calendar.HOUR_OF_DAY, 0);
            today.set(Calendar.MINUTE, 0);
            today.set(Calendar.SECOND, 0);
            today.set(Calendar.MILLISECOND, 0);
          }
          SimpleDateFormat sdf = new SimpleDateFormat(sDBDatetimeFormat);
          value = sdf.format(today.getTime());
        } else {
          value = (String) RequestUtils.lookup(pageContext, name, property, null);
        }
        if (value == null) {
          value = "";
        }
        sDatetimeStr = ResponseUtils.filter(value.toString());
      }

      // format the datetime string back to a
      if (!Utility.isEmpty(sDatetimeStr)) {
        if( sDatetimeStr.matches("^[0-9]{2}-[0-9]{2}-[0-9]{4}$") ) {
          String[] dateParts = sDatetimeStr.split("-");
          sDatetimeStr = dateParts[2] + "-" + dateParts[1] + "-" + dateParts[0];
        }
        SimpleDateFormat sdf = new SimpleDateFormat(sDBDatetimeFormat);
        SimpleDateFormat displayFormat = new SimpleDateFormat(dateFormat, new Locale("en", "US"));

        if (sDatetimeStr.length() != sDBDatetimeFormat.length()) {
          sDatetimeStr += " 00:00:00";
        }
        Date formatDate = sdf.parse(sDatetimeStr);
        if (formatDate != null) {
          Calendar cal = Calendar.getInstance();
          cal.setTime(formatDate);

          sDatePart = displayFormat.format(formatDate);
          iHourPart = cal.get(Calendar.HOUR_OF_DAY);
          iMinutePart = cal.get(Calendar.MINUTE);
        }
      }
      /*
      log.debug("db date format: "+sDBDatetimeFormat);
      log.debug("default today?: "+this.getDefaultToday());
      log.debug("date format: "+dateFormat);
      log.debug("date value: "+sDatetimeStr);
      log.debug("date part: "+sDatePart);
      log.debug("hour part: "+iHourPart);
      log.debug("minute part: "+iMinutePart);
      */
//      sOnBlurStr = (sOnBlurStr!=null?sOnBlurStr+";":"") + "return (g_Calendar.validateInput(this, '"+this.getDateFormat().toLowerCase()+"'));";

      sOnBlurStr = ((sOnBlurStr == null || (sOnBlurStr!=null && sOnBlurStr.indexOf("return (fcheck_date(this, '"+this.getDateFormat().toLowerCase()+
            "',"+this.getNeedReload()+","+this.getOnchange() +"));") < 0))?sOnBlurStr+";"+"return (fcheck_date(this, '"+this.getDateFormat().toLowerCase()+"',"+this.getNeedReload()+","+this.getOnchange() +"));":sOnBlurStr) ;      

      this.setOnblur(sOnBlurStr);

      sOnTimeChangeStr = (sOnTimeChangeStr!=null?sOnTimeChangeStr+";":"") + "return(formatActualValue(this, '"+this.getDateFormat().toLowerCase()+"', '"+(this.getDateFormat().indexOf("-")>-1? "-" : "/")+"'));";
      this.setOntimechange(sOnTimeChangeStr);

      this.setProperty("dummy_"+sPropertyName);
//      this.setProperty(sPropertyName);      
      if (date && time && textOnly) {
        this.setValue(sDatePart + " " + (iHourPart<10? ("0"+iHourPart) : Integer.toString(iHourPart)) + ":" + (iMinutePart<10? ("0"+iMinutePart) : Integer.toString(iMinutePart)));
      } else if (time && textOnly) {
        this.setValue((iHourPart<10? ("0"+iHourPart) : Integer.toString(iHourPart))+":"+(iMinutePart<10? ("0"+iMinutePart) : Integer.toString(iMinutePart)));
      } else {
        this.setValue(sDatePart);
      }
      if (date) {
        if (isViewDatePicker) {        	
          out.print("<input type=\"text\" name=\"" + this.getProperty() + "\"");
          out.print(" maxlength=\" " + this.getMaxlength() + "\" ");
          out.print(Utility.isEmpty(getStyleClass()) ? "" : "class=\"" + getStyleClass() + "\" ");
          out.print(" size=\" " + this.getSize() + "\" ");
          out.print(" value=\""+this.getValue() + "\" ");         
          out.print(" onblur=\""+this.getOnblur() + "\" >");
        } else {
          retValue = super.doStartTag();
        }
      }
//      this.setProperty(sPropertyName);
      // show the date picker if it is for editing
      String formBeanName = this.getFormName();
      if(Utility.isEmpty(formBeanName)){
    	formBeanName = ((org.apache.struts.taglib.html.FormTag) request.getAttribute(org.apache.struts.taglib.html.Constants.FORM_KEY)).getBeanName();
      }
      
      if ( (!textOnly && !(formTag!=null && formTag.getTextOnly())) || (!textOnly && isViewDatePicker ) ) {
        if (this.date) {
          // <a> tag for displaying the date picker
          out.print("<a ");
          out.print("href=\"javascript:void(0);\" ");
          out.print("onmouseover=\"if (timeoutId) clearTimeout(timeoutId);window.status='Show Calendar';return true;\" ");
//          out.print("onmouseout=\"if (timeoutDelay) calendarTimeout();window.status='';\" ");
          if (this.getChangeProperty()!=null){
            out.print("onclick=\"gfPop.fPopCalendar(document."+formBeanName+"." +this.getProperty()+ ",document."+formBeanName+"."+sPropertyName+",depRange,"+this.getNeedReload()+",'" +this.getDateFormat().toLowerCase()+ "',"+this.getDigital()+", "+"document."+formBeanName+"." +this.changeProperty+", "+"document."+formBeanName+"."+sChangePropertyName+", "+this.getOnchange() +","+this.getVerticalOffset()+","+this.getHorizontalOffset()+");\">");
          }else{
            out.print("onclick=\"gfPop.fPopCalendar(document."+formBeanName+"." +this.getProperty()+ ",document."+formBeanName+"."+sPropertyName+",depRange,"+this.getNeedReload()+",'" +this.getDateFormat().toLowerCase()+ "',"+this.getDigital()+", null, null, "+this.getOnchange() +","+this.getVerticalOffset()+","+this.getHorizontalOffset()+");\">");
          }
                    
//          out.print("onclick=\"g_Calendar.show(event,'" +this.getProperty()+ "', true,'" +this.getDateFormat().toLowerCase()+ "', " + this.getDate() + ", " + this.getTime() + (!"0".equals(this.getTopPos())? (",null,null,"+this.getTopPos()) : "") + ");return false;\"");
//          out.print(">");

          //print the html img tag for calendar image

          out.print("<img ");
          out.print("src=\""+WebUtil.getImage(pageContext.getRequest(), "IconCalendar.gif")+"\" ");
          out.print("name=\"imgCalendar_"+property+"\" ");
          out.print("align=\"absmiddle\" ");
          out.print("border=\"0\" ");
          out.print("alt=\"\"");
          out.print(">");

          // close the <a> tag
          out.println("</a>");
        }
        if (this.time) {
          //hour selection box
          out.print("<select name=\"hour_"+this.property+"\" ");
          out.print("onchange=\""+this.getOntimechange()+"\" ");
          out.println(">");
          for (int i=0; i<24; i++) {
            out.print("  <option value=\""+(i<10? ("0"+i): Integer.toString(i))+"\" "+(iHourPart==i? "selected": "")+">"+(i<10? ("0"+i): Integer.toString(i))+"</option>");
          }
          out.println("</select>");

          out.println(":");

          //minute selection box
          out.print("<select name=\"min_"+this.property+"\" ");
          out.print("onchange=\""+this.getOntimechange()+"\" ");
          out.println(">");
          for (int i=0; i<60; i++) {
            out.print("  <option value=\""+(i<10? ("0"+i): Integer.toString(i))+"\" "+(iMinutePart==i? "selected": "")+">"+(i<10? ("0"+i): Integer.toString(i))+"</option>");
          }
          out.println("</select>");
        }
      }

      //  field
      out.print("<input type=\"hidden\" ");
      out.print("name=\""+sPropertyName+"\" ");
      out.println("value=\""+sDatetimeStr+"\" >");
      this.setValue(null);
      return retValue;
    } catch (Exception e) {
      log.error(e, e);
      throw new JspException(e);
    }
  }

  /** Getter for property date.
   * @return Value of property date.
   */
  public boolean getDate() {
    return this.date;
  }

  /** Setter for property date.
   * @param date New value of property date.
   */
  public void setDate(boolean date) {
    this.date = date;
  }

  /** Getter for property time.
   * @return Value of property time.
   */
  public boolean getTime() {
    return this.time;
  }

  /** Setter for property time.
   * @param time New value of property time.
   */
  public void setTime(boolean time) {
    this.time = time;
  }

  /** Getter for property ontimechange.
   * @return Value of property ontimechange.
   */
  public String getOntimechange() {
    return this.ontimechange;
  }

  /** Setter for property ontimechange.
   * @param ontimechange New value of property ontimechange.
   */
  public void setOntimechange(String ontimechange) {
    this.ontimechange = ontimechange;
  }

  /** Getter for property defaultToday.
   * @return Value of property defaultToday.
   */
  public boolean getDefaultToday() {
    return this.defaultToday;
  }

  /** Setter for property defaultToday.
   * @param defaultToday New value of property defaultToday.
   */
  public void setDefaultToday(boolean defaultToday) {
    this.defaultToday = defaultToday;
  }

  
  /** Getter for property needReload.
   * @return Value of property needReload.
   */
  public boolean getNeedReload() {
    return this.needReload ;
  }

  /** Setter for property needReload.
   * @param needReload New value of property needReload.
   */
  public void setNeedReload(boolean needReload) {
    this.needReload  = needReload;
  }
  
  /** Getter for property digital.
   * @return Value of property digital.
   */
  public boolean getDigital() {
    return this.digital;
  }

  /** Setter for property digital.
   * @param digital New value of property digital.
   */
  public void setDigital(boolean digital) {
    this.digital   = digital;
  }
  
  public String getChangeProperty() {
  	return changeProperty;
  }
  
  public void setChangeProperty(String changeProperty) {
  	this.changeProperty = changeProperty;
  }
  
  public String getFormName() {
	  	return formName;
  }
	  
  public void setFormName(String formName) {
	this.formName = formName;
  }
  
  /**
   * release
   */
  
  public void release() {
    super.release();
    reset();
  }

}
